<?php

/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#namespace tehframework\validation;

/**
 * Encapsulates an object error, that is, a global reason for rejecting
 * an object.
 *
 * @see FieldError
 */
class ObjectError
{
	/**
	 * @var string
	 */
	private $objectName;
	
	/**
	 * @var array<string>
	 */
	private $codes;
	
	/**
	 * @var array
	 */
	private $arguments;
	
	/**
	 * @var string
	 */
	private $defaultMessage;
	
	/**
	 * Creates a new instance of the {@link ObjectError} class.
	 * 
	 * @param  string $objectName
	 *         The name of the affected object.
	 * @param  array<string> $codes
	 *         The codes to be used to resolve this message.
	 * @param  array $arguments
	 *         The array of arguments to be used to resolve this message.
	 * @param  string $defaultMessage
	 *         The default message to be used to resolve this message.
	 * @throws IllegalArgumentException
	 *         If the supplied $objectName is NULL or empty.
	 */
	public function __construct(
		$objectName,
		array $codes = null,
		array $arguments = null,
		$defaultMessage = null)
	{
		if (($objectName === null) || (trim($objectName) === ''))
		{
			throw new InvalidArgumentException(
				'Object name must not be NULL nor empty.');
		}
		
		$this->objectName     = $objectName;
		$this->codes          = $codes;
		$this->arguments      = $arguments;
		$this->defaultMessage = $defaultMessage;
	}
	
	/**
	 * @return string
	 */
	public function __toString()
	{
		return "Error in object '" .
			$this->objectName . "': " . $this->resolvableToString();
	}
	
	/**
	 * Returns the name of the affected object.
	 * 
	 * @return string
	 *         The name of the affected object.
	 */
	public function getObjectName()
	{
		return $this->objectName;
	}
	
	/**
	 * Returns the codes to be used to resolve this message, in the order that
	 * they should get tried. The last code will therefore be the default one.
	 * 
	 * @return array<string>
	 *         A string array of codes which are associated with this message.
	 */
	public function getCodes()
	{
		return $this->codes;
	}
	
	/**
	 * Returns the default code of this resolvable, that is,
	 * the last one in the codes array.
	 * 
	 * @return string?
	 *         The default code of this resolvable.
	 */
	public function getCode()
	{
		return !empty($this->codes) ? $this->codes[count($this->codes) - 1] : null;
	}
	
	/**
	 * Returns the array of arguments to be used to resolve this message.
	 * 
	 * @return array
	 *         An array of objects to be used as parameters to replace
	 *         placeholders within the message text.
	 */
	public function getArguments()
	{
		return $this->arguments;
	}
	
	/**
	 * Returns the default message to be used to resolve this message.
	 * 
	 * @return string?
	 *         The default message, or NULL if no default.
	 */
	public function getDefaultMessage()
	{
		return $this->defaultMessage;
	}
	
	final protected function resolvableToString()
	{
		return 'codes [' . implode(', ', (array)$this->codes) . ']; '
			. 'arguments [' . implode(', ', (array)$this->arguments) . ']; '
			. 'default message [' . $this->defaultMessage . ']';
	}
}